package com.stone.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.stone.bean.dto.SysUserPasswordDTO;
import com.stone.bean.dto.UserAddDTO;
import com.stone.bean.dto.UserUpdateDTO;
import com.stone.bean.vo.LoginVO;
import com.stone.config.SpringContextConfig;
import com.stone.config.exception.BusinessException;
import com.stone.constant.Const;
import com.stone.entity.SysUser;
import com.stone.entity.SysUserRole;
import com.stone.mapper.SysUserMapper;
import com.stone.service.SysUserRoleService;
import com.stone.service.SysUserService;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Objects;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author stone
 * @since 2022-04-02
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    @Resource
    private RedisTemplate redisTemplate;
    @Resource
    private SysUserRoleService sysUserRoleService;

    @Override
    public LoginVO selectByPhoneAndPwd(String phone, String password) {
        SysUser dbUser = getOne(new QueryWrapper<SysUser>().eq("phone", phone).eq("enable", true));
        //查询是否存在该用户
        if (Objects.isNull(dbUser)) {
            throw new BusinessException("用户名不存在或用户状态不可用");
        }
        //通过MD5和盐值解密密码进行校验
        String encryptPassword = SecureUtil.md5(password + dbUser.getSalt());
        if (!dbUser.getPassword().equals(encryptPassword)) {
            throw new BusinessException("用户名或密码错误");
        }
        LoginVO loginVo = new LoginVO();
        loginVo.setId(dbUser.getId());
        loginVo.setUserName(dbUser.getUserName());
        return loginVo;
    }

    @Override
    public void saveUserToken(Long id, String token) {
        SysUser dbUser = getById(id);
        if (Objects.isNull(dbUser)) {
            throw new BusinessException("用户不存在");
        }
        dbUser.setToken(token);
        this.baseMapper.updateById(dbUser);
    }

    @Override
    public void updateUserPassword(SysUserPasswordDTO dto, String token) {
        Object o = redisTemplate.opsForValue().get(Const.AUTH_PREFIX + token);
        LoginVO loginVO = JSON.parseObject(o.toString(), LoginVO.class);
        SysUser dbUser = getById(loginVO.getId());
        //通过MD5和盐值解密密码进行校验
        String encryptPassword = SecureUtil.md5(dto.getOldPassword() + dbUser.getSalt());
        if (!dbUser.getPassword().equals(encryptPassword)) {
            throw new BusinessException("原密码不正确");
        }
        SysUser sysUser = new SysUser();
        sysUser.setId(loginVO.getId());
        sysUser.setPassword(SecureUtil.md5(dto.getNewPassword() + dbUser.getSalt()));
        sysUser.setToken(StrUtil.EMPTY);
        sysUser.setUpdateBy(loginVO.getId());
        sysUser.setUpdateTime(LocalDateTime.now());
        updateById(sysUser);
    }

    @Override
    public boolean checkUserToken(Long id, String token) {
        SysUser dbUser = getById(id);
        if (Objects.isNull(dbUser)) {
            throw new BusinessException("用户不存在");
        }
        return token.equals(dbUser.getToken());
    }

    @Override
    public void reSetPassword(Long userId, String token) {
        SysUser dbUser = getById(userId);
        if (Objects.isNull(dbUser)) {
            throw new BusinessException("用户不存在");
        }
        SysUser sysUser = new SysUser();
        sysUser.setId(dbUser.getId());
        setDefaultPwd(sysUser);
        sysUser.setUpdateBy(SpringContextConfig.loginUserId(token));
        sysUser.setUpdateTime(LocalDateTime.now());
        updateById(dbUser);
    }

    @Override
    public void saveIp(Long id, String clientIP) {
        SysUser dbUser = getById(id);
        if (Objects.isNull(dbUser)) {
            throw new BusinessException("用户不存在");
        }
        dbUser.setLoginIp(clientIP);
        dbUser.setLoginDate(LocalDateTime.now());
        this.baseMapper.updateById(dbUser);
    }

    private void setDefaultPwd(SysUser sysUser) {
        String salt = RandomUtil.randomString(6);
        String pwd = SecureUtil.md5(Const.DEFAULT_PWD + salt);
        sysUser.setPassword(pwd);
        sysUser.setSalt(salt);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addUser(UserAddDTO dto) {
        SysUser sysUser = JSON.parseObject(JSON.toJSONString(dto), SysUser.class);
        sysUser.setCreateBy(SpringContextConfig.loginUserId(dto.getToken()));
        sysUser.setCreateTime(LocalDateTime.now());
        setDefaultPwd(sysUser);
        try {
            save(sysUser);
        } catch (DuplicateKeyException e) {
            throw new BusinessException("手机号已存在");
        }
        sysUserRoleService.saveBatchOfRoleList(dto.getRoleList(), sysUser.getId());
    }

    @Override
    public void updateUser(UserUpdateDTO dto) {
        SysUser dbUser = getById(dto.getId());
        if (Objects.isNull(dbUser)) {
            throw new BusinessException("用户不存在");
        }
        SysUser sysUser = new SysUser();
        sysUser.setId(dbUser.getId());
        sysUser.setUserName(dto.getUserName());
        sysUser.setPhone(dto.getPhone());
        sysUser.setEnable(dto.getEnable());
        sysUser.setUpdateBy(SpringContextConfig.loginUserId(dto.getToken()));
        sysUser.setUpdateTime(LocalDateTime.now());
        try {
            updateById(sysUser);
        } catch (DuplicateKeyException e) {
            throw new BusinessException("手机号已存在");
        }
        sysUserRoleService.remove(new QueryWrapper<SysUserRole>().eq("user_id", sysUser.getId()));
        sysUserRoleService.saveBatchOfRoleList(dto.getRoleList(), sysUser.getId());
    }
}
